package com.brillilab.service.core.topics.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.dao.mapper.topics.TopicMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.experiment.ExperimentStateEnum;
import com.brillilab.domain.enums.topic.TopicStateEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.domain.po.topics.Topic;
import com.brillilab.domain.po.topics.TopicDirection;
import com.brillilab.domain.po.topics.TopicTarget;
import com.brillilab.domain.vo.topics.TopicFileVo;
import com.brillilab.domain.vo.topics.TopicListVo;
import com.brillilab.domain.vo.topics.TopicScheduleVo;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.plans.IPlanService;
import com.brillilab.service.core.plans.IPlanTargetGroupService;
import com.brillilab.service.core.system.IFileManageService;
import com.brillilab.service.core.topics.ITopicDirectionService;
import com.brillilab.service.core.topics.ITopicMemberService;
import com.brillilab.service.core.topics.ITopicService;
import com.brillilab.service.core.topics.ITopicTargetService;
import com.github.pagehelper.PageHelper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class TopicServiceImpl implements ITopicService {

	@Resource
	private TopicMapper topicMapper;
	@Resource
	private IExperimentService experimentService;
	@Resource
	private ITopicDirectionService topicDirectionService;
	@Resource
	private ITopicTargetService topicTargetService;
	@Resource
	private IFileManageService fileManageService;
	@Resource
	private ITopicMemberService topicMemberService;
	@Resource
	private IPlanTargetGroupService planTargetGroupService;
	@Resource
	private IPlanService planService;

	@Override
	public PageVo<TopicListVo> getIndexTopicList(Long labId, List<Long> memberIds, Integer state, int pageNum,
			int pageSize) {
		PageHelper.startPage(pageNum, pageSize);
		List<Integer> states = null;
		if(state!= null && state==10) {
			states = Arrays.asList(TopicStateEnum.NOT_STARTED.getValue(), TopicStateEnum.UNDER_WAY.getValue());
		}else if(state!= null){
			states = Arrays.asList(state);
		}
		List<TopicListVo> list = topicMapper.getIndexTopicList(labId, memberIds, states);
		return new PageVo<TopicListVo>(setTopicStatistics(list));
	}

	@Override
	public List<TopicListVo> getIndexTopicList(Long labId, Long labMemberId) {
		List<TopicListVo> list = topicMapper.getIndexTopicList(labId, Arrays.asList(labMemberId),
				Arrays.asList(TopicStateEnum.NOT_STARTED.getValue(), TopicStateEnum.UNDER_WAY.getValue()));
		return setTopicStatistics(list);
	}

	private List<TopicListVo> setTopicStatistics(List<TopicListVo> voList) {
		if (!CollectionUtils.isEmpty(voList)) {
			List<Long> topicIds = voList.stream().map(TopicListVo::getTopicId).collect(Collectors.toList());
			List<Experiment> experimentList = experimentService.getListByTopicId(topicIds);

			List<TopicDirection> directionList = topicDirectionService.getListByTopicId(topicIds);
			List<TopicTarget> targetList = topicTargetService.getListByTopicId(topicIds);

			for (TopicListVo vo : voList) {
				int noFigureNum = 0;
				int figureNum = 0;
				int noFigNum = 0;
				int figNum = 0;
				int noExperNum = 0;
				int expectNum = 0;
				int noExpectNum = 0;
				// 研究内容列表
				List<TopicDirection> dirList = directionList.stream()
						.filter(direction -> direction.getTopicId().equals(vo.getTopicId()))
						.collect(Collectors.toList());

				for (TopicDirection direction : dirList) {
					// 实验流列表
					List<TopicTarget> tarList = targetList.stream()
							.filter(target -> target.getTopicDirectionId().equals(direction.getId()))
							.collect(Collectors.toList());

					int sbNoFigNum = 0;
					for (TopicTarget target : tarList) {
						List<Experiment> experList = experimentList.stream()
								.filter(exper -> target.getId().equals(exper.getTopicTargetId()))
								.collect(Collectors.toList());
						if (!CollectionUtils.isEmpty(experList)) {
							List<Experiment> experTarList = experList.stream()
									.filter(exper -> !ExperimentStateEnum.COMPLETE.getValue().equals(exper.getState()))
									.collect(Collectors.toList());
							if (!CollectionUtils.isEmpty(experTarList)) {
								noFigNum++;
								sbNoFigNum++;
							} else {
								figNum++;
							}

							for (Experiment exper : experList) {
								if (!ExperimentStateEnum.COMPLETE.getValue().equals(exper.getState())) {
									noExperNum++;
								} else if (BoolEnum.TRUE.getValue().equals(exper.getIsExpect())) {
									expectNum++;
								} else if (BoolEnum.FALSE.getValue().equals(exper.getIsExpect())) {
									noExpectNum++;
								}
							}
						} else {
							noFigNum = noFigNum + 1;
							sbNoFigNum = sbNoFigNum + 1;
						}

					}
					if (CollectionUtils.isEmpty(tarList)) {
						noFigureNum = noFigureNum + 1;
					} else if (sbNoFigNum > 0) {
						noFigureNum = noFigureNum + 1;
					} else {
						figureNum = figureNum + 1;
					}

				}

				vo.setNoFigureNum(noFigureNum);
				vo.setFigureNum(figureNum);
				vo.setNoFigNum(noFigNum);
				vo.setFigNum(figNum);
				vo.setNoExperNum(noExperNum);
				vo.setExpectNum(expectNum);
				vo.setNoExpectNum(noExpectNum);
			}
		}
		return voList;
	}

	@Override
	public Topic insert(Topic topic) {
		topicMapper.insert(topic);
		return topic;
	}

	@Override
	public List<Topic> selectList(List<Long> topicIds) {
		if (CollectionUtils.isNotEmpty(topicIds)) {
			return topicMapper.selectList(new LambdaQueryWrapper<Topic>().in(Topic::getId, topicIds)
					.eq(Topic::getIsDelete, BoolEnum.FALSE.getValue()));
		}
		return new ArrayList<>(0);
	}

	@Override
	public Topic selectById(Long topicId) {
		return topicMapper.selectById(topicId);
	}

	@Override
	public boolean update(Topic topic) {
		return topicMapper.updateById(topic) > 0;
	}

	@Override
	public List<Topic> selectListByLabId(Long labId) {
		return topicMapper.selectList(new LambdaQueryWrapper<Topic>().eq(Topic::getLabId, labId).eq(Topic::getIsDelete,
				BoolEnum.FALSE.getValue()));
	}

	@Override
	public List<Topic> getMainExecutorTopicList(Long executorId) {
		return topicMapper.selectList(new LambdaQueryWrapper<Topic>().eq(Topic::getExecutorId, executorId)
				.ne(Topic::getState, TopicStateEnum.COMPLETE.getValue())
				.eq(Topic::getIsDelete, BoolEnum.FALSE.getValue()));
	}

	@Override
	public List<Topic> selectList(Long labMemberId, List<Integer> states) {
		return topicMapper.selectTopicList(labMemberId, states);
	}

	@Override
	public List<Topic> selectListByLabMemberIds(Long labId, List<Long> labMemberIds, List<Integer> states) {
		LambdaQueryWrapper<Topic> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Topic::getLabId, labId);
		wrapper.in(Topic::getExecutorId, labMemberIds);
		wrapper.in(Topic::getState, states);
		wrapper.eq(Topic::getIsDelete, BoolEnum.FALSE.getValue());
		return topicMapper.selectList(wrapper);
	}

	@Override
	public int getTopicCount(Long labId) {
		LambdaQueryWrapper<Topic> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Topic::getLabId, labId);
		wrapper.eq(Topic::getIsDelete, BoolEnum.FALSE.getValue());
		return topicMapper.selectCount(wrapper);
	}

	@Override
	public int getTopicCountByExecutorId(Long executorId) {
		LambdaQueryWrapper<Topic> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Topic::getExecutorId, executorId);
		wrapper.eq(Topic::getIsDelete, BoolEnum.FALSE.getValue());
		return topicMapper.selectCount(wrapper);
	}

	@Override
	public int updateById(Topic topic) {
		return topicMapper.updateById(topic);
	}

	@Override
	public void setTopicStateUnderWay(Long topicId) {
		Topic topic = topicMapper.selectById(topicId);
		if (topic.getState().equals(TopicStateEnum.NOT_STARTED.getValue())) {
			if (topic.getStartTime() == null) {
				topic.setStartTime(new Date());
			}
			topic.setState(TopicStateEnum.UNDER_WAY.getValue());
			topicMapper.updateById(topic);
		}
	}

	@Override
	public List<Topic> recycleBinList(Long labId, List<Long> memberIds) {
		LambdaQueryWrapper<Topic> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Topic::getLabId, labId);
		wrapper.eq(Topic::getIsDelete, IsDeleteEnum.YES.getValue());
		if (!CollectionUtils.isEmpty(memberIds)) {
			wrapper.in(Topic::getExecutorId, memberIds);
		}
		return topicMapper.selectList(wrapper);
	}

	@Override
	public Integer getTopicCountByLabMemberId(Long labMemberId) {
		return topicMapper.getTopicCountByLabMemberId(labMemberId);
	}

	@Override
	public Integer getTopicCountByLabId(Long labId) {
		LambdaQueryWrapper<Topic> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Topic::getLabId, labId);
		wrapper.eq(Topic::getIsDelete, IsDeleteEnum.NO.getValue());
		return topicMapper.selectCount(wrapper);
	}

	@Override
	public List<TopicFileVo> getTopicFileList(Long labId, Long topicId) {
		List<TopicFileVo> topicFileList = new ArrayList<TopicFileVo>();
		List<FileManage> fileList1 = fileManageService.selectList(OssFileEnum.TopicProjectPlanFile, topicId);
		topicFileList.add(new TopicFileVo(OssFileEnum.TopicProjectPlanFile.getKey(), "项目计划书", fileList1));

		List<FileManage> fileList2 = fileManageService.selectList(OssFileEnum.TopicProjectBudgetFile, topicId);
		topicFileList.add(new TopicFileVo(OssFileEnum.TopicProjectBudgetFile.getKey(), "项目预算表", fileList2));

		List<FileManage> fileList3 = fileManageService.selectList(OssFileEnum.TopicResultDataFile, topicId);
		topicFileList.add(new TopicFileVo(OssFileEnum.TopicResultDataFile.getKey(), "结果数据", fileList3));

		List<FileManage> fileList4 = fileManageService.selectList(OssFileEnum.TopicRepresentativeWorksFile, topicId);
		topicFileList.add(new TopicFileVo(OssFileEnum.TopicRepresentativeWorksFile.getKey(), "代表性论著", fileList4));

		List<FileManage> fileList5 = fileManageService.selectList(OssFileEnum.TopicPatentFile, topicId);
		topicFileList.add(new TopicFileVo(OssFileEnum.TopicPatentFile.getKey(), "专利文档", fileList5));

		List<FileManage> fileList6 = fileManageService.selectList(OssFileEnum.TopicOtherFile, topicId);
		topicFileList.add(new TopicFileVo(OssFileEnum.TopicOtherFile.getKey(), "其他", fileList6));
		return topicFileList;
	}

	@Override
	public void deleteById(Long topicId) {
		// 删除课题
		Topic topic = new Topic();
		topic.setId(topicId);
		topic.setIsDelete(BoolEnum.TRUE.getValue());
		boolean update = topicMapper.updateById(topic) > 0;
		Assert.isTrue(update, "删除该课题失败");
		topicMemberService.deleteMembers(topicId);
		planTargetGroupService.delete(topicId, null, null);
		planService.deleteByTopicId(topicId);
	}

	/**
	 * 新曾课题时判断主执行人和成员是否存在于他人课题
	 * 
	 * @param membersAndExecutor
	 * @param executorId
	 * @return
	 */
	@Override
	public boolean executorOrMemberExistInOtherTopic(List<Long> membersAndExecutor, Long executorId) {
		return topicMapper.executorOrMemberExistInOtherTopic(membersAndExecutor, executorId) > 0;
	}

	@Override
	public PageVo<TopicScheduleVo> getTopicSchedule(Long labId, List<Long> memberIds, int pageNum, int pageSize) {
		PageHelper.startPage(pageNum, pageSize);
		List<TopicScheduleVo> list = topicMapper.getTopicSchedule(labId, memberIds);
		return new PageVo<TopicScheduleVo>(list);
	}

	@Override
	public List<Topic> getTopicByMainExecutorId(Long mainExecutorId) {
		return topicMapper.selectList(new LambdaQueryWrapper<Topic>().eq(Topic::getExecutorId, mainExecutorId));
	}
}
